package org.groupg.project.processManager;

import com.formdev.flatlaf.FlatIntelliJLaf;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

public class ProcessManagerGUI {
    private ApplicationProcessManager processManager = new ApplicationProcessManager();
    private JTextArea logArea;
    private JComboBox<String> processComboBox;
    private JButton startBtn, stopBtn, refreshBtn, forceStopBtn, clearLogBtn;
    private JTextField commandField, workingDirField;
    private JCheckBox useScriptCheckbox;

    public ProcessManagerGUI() {
        initializeUI();
        setupEventHandlers(); // 集中设置所有事件处理器
        EventBus.subscribe(this::handleProcessEvent);
    }

    private void setupEventHandlers() {
        // 1. 按钮点击事件
        setupButtonHandlers();

        // 2. 文本框事件
        setupTextFieldHandlers();

        // 3. 复选框事件
        setupCheckboxHandlers();

        // 4. 组合框事件
        setupComboBoxHandlers();

        // 5. 窗口事件
        setupWindowHandlers();

        // 6. 键盘快捷键
        setupKeyboardShortcuts();
    }

    private void setupButtonHandlers() {
        // 启动按钮
        startBtn.addActionListener(e -> {
            String processName = (String) processComboBox.getSelectedItem();
            startProcess(processName);
        });

        // 停止按钮
        stopBtn.addActionListener(e -> {
            String processName = (String) processComboBox.getSelectedItem();
            stopProcess(processName);
        });

        // 强制停止按钮
        forceStopBtn.addActionListener(e -> {
            String processName = (String) processComboBox.getSelectedItem();
            forceStopProcess(processName);
        });

        // 刷新按钮
        refreshBtn.addActionListener(e -> refreshAllStatus());

        // 清空日志按钮
        clearLogBtn.addActionListener(e -> clearLog());

        // 浏览工作目录按钮
        JButton browseBtn = new JButton("浏览...");
        browseBtn.addActionListener(e -> browseWorkingDirectory());
    }

    private void setupTextFieldHandlers() {
        // 命令输入框的回车事件
        commandField.addActionListener(e -> {
            String command = commandField.getText().trim();
            if (!command.isEmpty()) {
                executeCustomCommand(command);
            }
        });

        // 工作目录输入框的焦点事件
        workingDirField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                validateWorkingDirectory();
            }
        });
    }

    private void setupCheckboxHandlers() {
        // 使用脚本复选框
        useScriptCheckbox.addActionListener(e -> {
            boolean useScript = useScriptCheckbox.isSelected();
            updateUIForScriptUsage(useScript);
        });
    }

    private void setupComboBoxHandlers() {
        // 进程选择组合框
        processComboBox.addActionListener(e -> {
            String selectedProcess = (String) processComboBox.getSelectedItem();
            if (selectedProcess != null) {
                updateUIForSelectedProcess(selectedProcess);
            }
        });
    }

    private void setupWindowHandlers() {
        // 获取主窗口（需要在initializeUI中保存窗口引用）
        JFrame mainFrame = getMainFrame();

        // 窗口关闭事件
        mainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                cleanupBeforeExit();
            }
        });
    }

    private void setupKeyboardShortcuts() {
        // 设置键盘快捷键
        JRootPane rootPane = getMainFrame().getRootPane();

        // Ctrl+S 启动进程
        rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK), "startProcess");
        rootPane.getActionMap().put("startProcess", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startBtn.doClick();
            }
        });

        // Ctrl+Q 停止进程
        rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK), "stopProcess");
        rootPane.getActionMap().put("stopProcess", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                stopBtn.doClick();
            }
        });

        // Ctrl+L 清空日志
        rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(KeyStroke.getKeyStroke(KeyEvent.VK_L, InputEvent.CTRL_DOWN_MASK), "clearLog");
        rootPane.getActionMap().put("clearLog", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                clearLogBtn.doClick();
            }
        });
    }

    // 具体的业务方法实现
    private void startProcess(String processName) {
        if (processName == null || processName.trim().isEmpty()) {
            showError("请选择或输入进程名称");
            return;
        }

        new SwingWorker<Boolean, String>() {
            @Override
            protected Boolean doInBackground() throws Exception {
                publish("正在启动进程: " + processName);

                if ("tomcat".equals(processName)) {
                    String tomcatHome = workingDirField.getText().trim();
                    if (tomcatHome.isEmpty()) {
                        publish("错误: 请设置Tomcat工作目录");
                        return false;
                    }

                    ProcessInfo info = processManager.startTomcat(tomcatHome);
                    publish("Tomcat启动成功, PID: " + info.getPid());
                    return true;
                } else {
                    // 处理其他进程
                    String command = commandField.getText().trim();
                    if (command.isEmpty()) {
                        publish("错误: 请设置启动命令");
                        return false;
                    }

                    String[] cmdArray = parseCommand(command);
                    File workingDir = new File(workingDirField.getText().trim());
                    ProcessInfo info = processManager.startProcess(processName, cmdArray, workingDir);
                    publish("进程启动成功, PID: " + info.getPid());
                    return true;
                }
            }

            @Override
            protected void process(List<String> chunks) {
                for (String message : chunks) {
                    appendLog(message);
                }
            }

            @Override
            protected void done() {
                try {
                    Boolean success = get();
                    if (success) {
                        startBtn.setEnabled(false);
                        stopBtn.setEnabled(true);
                        forceStopBtn.setEnabled(true);
                    }
                } catch (Exception ex) {
                    appendLog("启动失败: " + ex.getMessage());
                }
            }
        }.execute();
    }

    private void stopProcess(String processName) {
        new SwingWorker<Boolean, String>() {
            @Override
            protected Boolean doInBackground() throws Exception {
                publish("正在停止进程: " + processName);

                boolean success;
                if (useScriptCheckbox.isSelected() && "tomcat".equals(processName)) {
                    String tomcatHome = workingDirField.getText().trim();
                    success = processManager.stopTomcat(tomcatHome);
                } else {
                    success = processManager.stopProcess(processName);
                }

                if (success) {
                    publish("进程停止成功: " + processName);
                } else {
                    publish("停止进程失败: " + processName);
                }
                return success;
            }

            @Override
            protected void process(List<String> chunks) {
                for (String message : chunks) {
                    appendLog(message);
                }
            }

            @Override
            protected void done() {
                try {
                    Boolean success = get();
                    if (success) {
                        startBtn.setEnabled(true);
                        stopBtn.setEnabled(false);
                        forceStopBtn.setEnabled(false);
                    }
                } catch (Exception ex) {
                    appendLog("停止过程中发生错误: " + ex.getMessage());
                }
            }
        }.execute();
    }

    private void forceStopProcess(String processName) {
        int result = JOptionPane.showConfirmDialog(
                getMainFrame(),
                "确定要强制终止进程 " + processName + " 吗？这可能导致数据丢失！",
                "确认强制终止",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE
        );

        if (result == JOptionPane.YES_OPTION) {
            new SwingWorker<Boolean, Void>() {
                @Override
                protected Boolean doInBackground() throws Exception {
                    return processManager.forceStopProcess(processName);
                }

                @Override
                protected void done() {
                    try {
                        Boolean success = get();
                        if (success) {
                            appendLog("进程已强制终止: " + processName);
                            startBtn.setEnabled(true);
                            stopBtn.setEnabled(false);
                            forceStopBtn.setEnabled(false);
                        } else {
                            appendLog("强制终止失败: " + processName);
                        }
                    } catch (Exception ex) {
                        appendLog("强制终止错误: " + ex.getMessage());
                    }
                }
            }.execute();
        }
    }

    private void refreshAllStatus() {
        List<ProcessInfo> processes = processManager.getManagedProcesses();
        appendLog("=== 进程状态刷新 ===");

        for (ProcessInfo process : processes) {
            ProcessStatus status = processManager.getProcessStatus(process.getName());
            appendLog(process.getName() + ": " + status + " (PID: " + process.getPid() + ")");
        }
        appendLog("==================");
    }

    private void clearLog() {
        logArea.setText("");
        appendLog("日志已清空 " + new Date());
    }

    private void browseWorkingDirectory() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setDialogTitle("选择工作目录");

        int result = chooser.showOpenDialog(getMainFrame());
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedDir = chooser.getSelectedFile();
            workingDirField.setText(selectedDir.getAbsolutePath());
        }
    }

    private void executeCustomCommand(String command) {
        appendLog("执行命令: " + command);
        // 实现自定义命令执行逻辑
    }

    private void validateWorkingDirectory() {
        String path = workingDirField.getText().trim();
        if (!path.isEmpty()) {
            File dir = new File(path);
            if (!dir.exists() || !dir.isDirectory()) {
                showError("工作目录不存在或不是有效的目录: " + path);
                workingDirField.requestFocus();
            }
        }
    }

    private void updateUIForScriptUsage(boolean useScript) {
        // 根据是否使用脚本更新UI状态
        commandField.setEnabled(!useScript);
        // 其他相关UI更新
    }

    private void updateUIForSelectedProcess(String processName) {
        // 根据选择的进程更新UI
        if ("tomcat".equals(processName)) {
            useScriptCheckbox.setSelected(true);
            useScriptCheckbox.setEnabled(true);
        } else {
            useScriptCheckbox.setSelected(false);
            useScriptCheckbox.setEnabled(false);
        }
    }

    private void cleanupBeforeExit() {
        // 程序退出前的清理工作
        appendLog("正在关闭进程管理器...");

        // 停止所有监控的进程
        List<ProcessInfo> processes = processManager.getManagedProcesses();
        for (ProcessInfo process : processes) {
            if (processManager.getProcessStatus(process.getName()) == ProcessStatus.RUNNING) {
                appendLog("正在停止: " + process.getName());
                processManager.stopProcess(process.getName());
            }
        }

        System.exit(0);
    }

    // 辅助方法
    private void showError(String message) {
        JOptionPane.showMessageDialog(getMainFrame(), message, "错误", JOptionPane.ERROR_MESSAGE);
        appendLog("错误: " + message);
    }

    private void appendLog(String message) {
        SwingUtilities.invokeLater(() -> {
            logArea.append(new Date() + " - " + message + "\n");
            logArea.setCaretPosition(logArea.getDocument().getLength());
        });
    }

    private JFrame getMainFrame() {
        // 返回主窗口引用（需要在initializeUI中设置）
        return (JFrame) SwingUtilities.getWindowAncestor(logArea);
    }

    private String[] parseCommand(String command) {
        // 简单的命令解析，支持带空格的参数
        return command.split("\\s+");
    }

    // 事件总线处理
    private void handleProcessEvent(Object event) {
        SwingUtilities.invokeLater(() -> {
            if (event instanceof ProcessOutputEvent) {
                ProcessOutputEvent outputEvent = (ProcessOutputEvent) event;
                appendLog("[" + outputEvent.getProcessName() + "] " + outputEvent.getOutput());
            } else if (event instanceof ProcessTerminatedEvent) {
                ProcessTerminatedEvent terminatedEvent = (ProcessTerminatedEvent) event;
                appendLog("进程 " + terminatedEvent.getProcessName() + " 已退出，退出码: " + terminatedEvent.getExitCode());

                // 更新按钮状态
                startBtn.setEnabled(true);
                stopBtn.setEnabled(false);
                forceStopBtn.setEnabled(false);
            }
        });
    }

    private void initializeUI() {
        JFrame frame = new JFrame("进程管理器");
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 改为自己处理关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                cleanupBeforeExit();
            }
        });

        // 创建主面板
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 创建控制面板
        JPanel controlPanel = createControlPanel();
        mainPanel.add(controlPanel, BorderLayout.NORTH);

        // 创建日志面板
        JPanel logPanel = createLogPanel();
        mainPanel.add(logPanel, BorderLayout.CENTER);

        frame.add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null); // 居中显示
        frame.setVisible(true);
    }

    private JPanel createControlPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        // 第一行：进程选择
        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(new JLabel("进程:"), gbc);

        gbc.gridx = 1;
        gbc.gridy = 0;
        processComboBox = new JComboBox<>(new String[]{"tomcat", "自定义进程"});
        panel.add(processComboBox, gbc);

        // 第二行：命令输入
        gbc.gridx = 0;
        gbc.gridy = 1;
        panel.add(new JLabel("命令:"), gbc);

        gbc.gridx = 1;
        gbc.gridy = 1;
        commandField = new JTextField(30);
        panel.add(commandField, gbc);

        // 第三行：工作目录
        gbc.gridx = 0;
        gbc.gridy = 2;
        panel.add(new JLabel("工作目录:"), gbc);

        gbc.gridx = 1;
        gbc.gridy = 2;
        workingDirField = new JTextField(30);
        panel.add(workingDirField, gbc);

        gbc.gridx = 2;
        gbc.gridy = 2;
        JButton browseBtn = new JButton("浏览...");
        panel.add(browseBtn, gbc);

        // 第四行：选项和按钮
        gbc.gridx = 0;
        gbc.gridy = 3;
        useScriptCheckbox = new JCheckBox("使用停止脚本", true);
        panel.add(useScriptCheckbox, gbc);

        gbc.gridx = 1;
        gbc.gridy = 3;
        JPanel buttonPanel = new JPanel(new FlowLayout());
        startBtn = new JButton("启动");
        stopBtn = new JButton("停止");
        forceStopBtn = new JButton("强制停止");
        refreshBtn = new JButton("刷新状态");
        clearLogBtn = new JButton("清空日志");

        buttonPanel.add(startBtn);
        buttonPanel.add(stopBtn);
        buttonPanel.add(forceStopBtn);
        buttonPanel.add(refreshBtn);
        buttonPanel.add(clearLogBtn);

        panel.add(buttonPanel, gbc);

        return panel;
    }

    private JPanel createLogPanel() {
        JPanel panel = new JPanel(new BorderLayout());

        logArea = new JTextArea(20, 80);
        logArea.setEditable(false);
        logArea.setFont(new Font("Monospaced", Font.PLAIN, 12));

        JScrollPane scrollPane = new JScrollPane(logArea);
        scrollPane.setBorder(BorderFactory.createTitledBorder("进程输出"));

        panel.add(scrollPane, BorderLayout.CENTER);

        return panel;
    }

    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(new FlatIntelliJLaf());
        SwingUtilities.invokeLater(ProcessManagerGUI::new);
    }
}